package org.lionzhou.chatGG.web.util.enterprise;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.lionzhou.chatGG.web.client.dto.ChatResDto;
import org.lionzhou.chatGG.web.config.GGConfig;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;

/**
 * @Description
 * @Author ZhouLiangCheng
 * @Date 2023/2/10
 * @Version 1.0
 */
@Component
@Slf4j
@AllArgsConstructor
public class EnterpriseDingDingUtil {

    ObjectMapper objectMapper;

    GGConfig ggConfig;

    Optional<AccessTokenDto> accessTokenDto = Optional.empty();

    public void post(String content, String openConversationId) {
        EnterpriseMsgDto msgDto = new EnterpriseMsgDto();
        msgDto.setMsgKey("sampleText");
        msgDto.setOpenConversationId(openConversationId);
        msgDto.setRobotCode(ggConfig.getAppKey());
        try {
            SampleTextDto sampleTextDto = new SampleTextDto();
            sampleTextDto.setContent(content);
            msgDto.setMsgParam(objectMapper.writeValueAsString(sampleTextDto));
            String body = objectMapper.writeValueAsString(msgDto);
            log.info("body:{}", body);
            HttpRequest httpRequest = HttpRequest.newBuilder()
                    .timeout(Duration.ofSeconds(900))
                    .uri(URI.create("https://api.dingtalk.com/v1.0/robot/groupMessages/send"))
                    .header("Content-Type", "application/json")
                    .header("x-acs-dingtalk-access-token", getAccessToken().getAccessToken())
                    .POST(HttpRequest.BodyPublishers.ofString(body))
                    .build();
            HttpResponse.BodyHandler<byte[]> bodyHandler = HttpResponse.BodyHandlers.ofByteArray();
            CompletableFuture<HttpResponse<byte[]>> future = HttpClient.newHttpClient().sendAsync(httpRequest, bodyHandler);

            ChatResDto resDto = future.thenApply(HttpResponse::body)
                    .thenApply((r) -> {
                        log.info(new String(r));
                        ChatResDto chatResDto = null;
                        try {
                            chatResDto = objectMapper.readValue(r, ChatResDto.class);
                            log.info(chatResDto.toString());
                            if ("InvalidAuthentication".equalsIgnoreCase(chatResDto.getCode())) {
                                // 刷新token
                                accessTokenDto = Optional.empty();
                            }
                            return chatResDto;
                        } catch (IOException e) {
                            log.error(e.getMessage());
                        }
                        return null;
                    })
                    .join();
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    public AccessTokenDto getAccessToken() {
        if (accessTokenDto.isPresent()) {
            return accessTokenDto.get();
        }

        try {
            String body = String.format("{\"appKey\":\"%s\",\"appSecret\":\"%s\"}", ggConfig.getAppKey(), ggConfig.getAppSecret());
            log.info("body:{}", body);
            HttpRequest httpRequest = HttpRequest.newBuilder()
                    .timeout(Duration.ofSeconds(900))
                    .uri(URI.create("https://api.dingtalk.com/v1.0/oauth2/accessToken"))
                    .header("Content-Type", "application/json")
                    .POST(HttpRequest.BodyPublishers.ofString(body))
                    .build();
            HttpResponse.BodyHandler<byte[]> bodyHandler = HttpResponse.BodyHandlers.ofByteArray();
            CompletableFuture<HttpResponse<byte[]>> future = HttpClient.newHttpClient().sendAsync(httpRequest, bodyHandler);

            AccessTokenDto resDto = future.thenApply(HttpResponse::body)
                    .thenApply((r) -> {
                        log.info(new String(r));
                        try {
                            return objectMapper.readValue(r, AccessTokenDto.class);
                        } catch (IOException e) {
                            log.error(e.getMessage());
                        }
                        return null;
                    })
                    .join();
            return resDto;
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return new AccessTokenDto();
    }
}
